home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / snip9707.zip / MDALLOC.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  6KB  |  164 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*   Written by Blair Haukedal 91/09 and placed in the public domain */
  4.  
  5. /*  mdalloc - a multi dimensional array allocator
  6.  *  mdfree  - a companion function to mdalloc for freeing storage
  7.  *  synopsis:
  8.  *      void *mdalloc(int ndim, int width, ...);
  9.  *          where:  ndim:   number of array dimensions
  10.  *                  width:  size of elements in array
  11.  *                  variable args are dimensions of array
  12.  *          returns: n-way indirect pointer to allocated storage
  13.  *                   or NULL if insufficient storage
  14.  *
  15.  *      void mdfree(void *p, ndim);
  16.  *          where:  p:      pointer to storage obtained by mdalloc
  17.  *                  ndim:   number of dimensions used in mdalloc
  18.  *
  19.  *  example:
  20.  *      int ***tip;
  21.  *      tip = mdalloc(3, sizeof(int), 2, 3, 4);
  22.  *        tip will be a triple indirect pointer to a 3 dimensional array
  23.  *        tip[0][0][0] refers to the first int in a contiguous area of
  24.  *                     storage that is 2*3*4*sizeof(int) bytes long
  25.  *        tip[0][0] is the address of the first int
  26.  *      memset can be used to initialize array elements as follows:
  27.  *        memset(tip[0][0], 0, 2*3*4*sizeof(int));
  28.  *      mdfree is used to free storage obtained with mdalloc:
  29.  *        mdfree(tip, 3)
  30.  *
  31.  *  notes:
  32.  *      - must be compiled with appropriate memory model
  33.  *      - memory is allocated for each dimension for indirect pointers
  34.  *          eg. 3x4x5 array of longs
  35.  *              (assuming 4 byte longs, small mem model)
  36.  *              p = mdalloc(3, sizeof(long), 3, 4, 5)            - bytes
  37.  *                  3       pointers allocated for 1st dimension -  6
  38.  *                  3x4     pointers allocated for 2nd dimension -  24
  39.  *                  3x4x5   longs allocated for array elements   -  240
  40.  *              total of 270 bytes allocated
  41.  *      - if insufficient memory, nothing will be allocated.
  42.  *          ie. intermediate pointer arrays that were successfully
  43.  *              allocated will be freed.
  44.  *      - the intent of mdalloc is to facilitate dynamic array creation,
  45.  *        it will use more memory than statically declared arrays, and
  46.  *        the required dereferencing will be slower than the use of
  47.  *        statically declared arrays.
  48.  *      - this function assumes that sizeof(char) == 1.
  49.  */
  50.  
  51. #include <stdarg.h>
  52. #include <stdlib.h>
  53. #include "snparray.h"
  54.  
  55. static void **md2(int n_units, int ndim, int *dims);
  56. static void md3(char ***tip, int n_units, int ndim, int *dims);
  57.  
  58. static int w_units;
  59.  
  60. /* mdalloc: entry point for mdalloc function described above
  61.  *      - reduces variable arg list to fixed list with last arg
  62.  *      represented as pointer to int (array dimensions).
  63.  *      Calls md2 to allocate storage.
  64.  *      Calls md3 to initialize intermediate pointers.
  65.  *      Returns pointer.
  66.  */
  67.  
  68. void *mdalloc(int ndim, int width, ...)
  69. {
  70.       va_list argp;
  71.       int *dims, i;
  72.       char ***tip;
  73.  
  74.       va_start(argp, width);
  75.  
  76.       /* allocate storage for variable args (dimensions) */
  77.  
  78.       dims = malloc(ndim*sizeof(int));
  79.       if(dims == NULL)
  80.             return NULL;
  81.  
  82.       /* initialize dimensions array for subsequent calls */
  83.  
  84.       for(i=0; i<ndim; i++)
  85.             dims[i] = va_arg(argp,int);
  86.  
  87.       w_units = width;    /* global used by md2 and md3 */
  88.  
  89.       /* allocate required pointer and array element storage */
  90.  
  91.       tip = (char ***)md2(dims[0], ndim, &dims[1]);
  92.  
  93.       if(ndim>1 && tip)
  94.             md3(tip, dims[0], ndim-1, &dims[1]); /* init pointers */
  95.  
  96.       free(dims);
  97.       return tip;
  98. }
  99.  
  100. /* mdfree:  companion function to mdalloc
  101.  *          frees storage obtained by mdalloc
  102.  */
  103.  
  104. void mdfree(void *tip, int ndim)
  105. {
  106.       if(ndim == 1)
  107.             free(tip);
  108.       else
  109.       {
  110.             mdfree(((void **)tip)[0], ndim-1);
  111.             free(tip);
  112.       }
  113. }
  114.  
  115. /* md2:  allocates storage for n-way indirect pointer arrays
  116.  *       allocates storage for requested array elements
  117.  */
  118.  
  119. static void **md2(int n_units, int ndim, int *dims)
  120. {
  121.       char **tip;
  122.  
  123.       if(ndim == 1)
  124.             /* recursed to final dimension - allocate element storage */
  125.             tip = malloc(n_units*w_units);
  126.       else
  127.       {
  128.             /* allocate pointer array for dimension n */
  129.             tip = malloc(n_units*sizeof(char *));
  130.             if(tip)
  131.             {
  132.                   /* recurse until final dimension */
  133.                   tip[0] = (char *)md2(n_units*dims[0], ndim-1, &dims[1]);
  134.                   if(tip[0] == NULL)
  135.                   {
  136.                         /* allocate error - fall back up freeing everything */
  137.                         free(tip);
  138.                         tip = NULL;
  139.                   }
  140.             }
  141.       }
  142.       return (void **)tip;
  143. }
  144.  
  145. /* md3: initializes indirect pointer arrays */
  146.  
  147. static void md3(char ***tip, int n_units, int ndim, int *dims)
  148. {
  149.       int i;
  150.  
  151.       for(i=1; i<n_units; i++)
  152.       {
  153.             if(ndim == 1)
  154.                   /* final dimension - must scale by element width */
  155.                   tip[i] = (char **)((char *)tip[0] + i*dims[0]*w_units);
  156.             else
  157.                   /* intermediate dimension - scale by pointer size */
  158.                   tip[i] = tip[0] + i*dims[0];
  159.       }
  160.       if(ndim > 1)
  161.             /* not at final dimension - continue to recurse */
  162.             md3((char ***)tip[0], n_units*dims[0], ndim-1, &dims[1]);
  163. }
  164.